/*
 * Copyright 2009 Eat Local Food, LLC
 * Copyright (c) 2007 osCommerce (this file was written after
 * code review of osCommerce).
 *
 * This file is part of gwtCommerce.
 *
 * gwtCommerce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * gwtCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gwtCommerce.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elf.gwt.common.client.model;

import java.util.ArrayList;
import java.util.List;

import com.elf.gwt.common.client.exception.TooManyItemsInCartException;

public class CartModel
{
	protected boolean uploadCartRequired;

	protected List<DetailedProductModel> products;
	protected double cartPrice;

	public CartModel()
	{
		this.products = new ArrayList<DetailedProductModel>();
	}

	public List<DetailedProductModel> getProducts() {
		return products;
	}

	public void addProduct(DetailedProductModel productModel) throws TooManyItemsInCartException {

		//Find out if there is a match to add the quantity to, or should this be added by itself
		DetailedProductModel model = null;
		boolean match = false;
		int sz = products.size();
		int qty = 0;
		for (int i=0; i< sz; i++)
		{
			model = products.get(i);
			qty = qty + model.getCartQuantity();
		}
		qty = qty + productModel.getCartQuantity();
		if (qty > productModel.getCartQuantityMax()) throw new TooManyItemsInCartException();

		for (int i=0; i< sz; i++)
		{
			model = products.get(i);
			if (model.getId() == productModel.getId())
			{
				int sz1 = model.getCartOptions().size();
				int sz2 = productModel.getCartOptions().size();
				if (sz1 == 0 && sz2 == 0)
				{
					match = true;
				}
				else if (sz1 != sz2)
				{
					match = false;
				}
				else
				{
					match = true;
					List<AttributeValueModel>values1 = model.getCartOptions();
					List<AttributeValueModel>values2 = productModel.getCartOptions();
					for (int j=0; j<sz1; j++)
					{
						AttributeValueModel value1 = values1.get(j);
						AttributeValueModel value2 = values2.get(j);
						if (value1.getId() != value2.getId())
						{
							match = false;
							break;
						}
					}
				}
			}
			if (match) break;
		}

		if (match)
		{
			model.setCartQuantity(model.getCartQuantity() + productModel.getCartQuantity());
		}
		else 
		{
			products.add(productModel);
		}

		updateProductPrices();
		uploadCartRequired = true;
	}

	public void removeProduct(ProductModel productModel) {
		products.remove(productModel);
		updateProductPrices();
		uploadCartRequired = true;
	}

	public void updateProductPrices() {
		DetailedProductModel model = null;
		double totalCartPrice = 0.0;
		int sz = products.size();
		for (int i=0; i< sz; i++)
		{
			model = products.get(i);
			double price = model.getPrice();

			double specialPrice = model.getSpecialPrice();
			if (specialPrice > 0.00000001 && price > specialPrice) price = specialPrice;

			int discountQuantity = getDiscountCategoryQuantities(model.getDiscountCategory());
			if (discountQuantity < 1) discountQuantity = model.getCartQuantity();

			double discountPrice = model.getDiscountPrice(discountQuantity);
			if (discountPrice > 0.00000001 && price > discountPrice) price = discountPrice;

			int sz1 = model.getCartOptions().size();
			List<AttributeValueModel>values = model.getCartOptions();
			for (int j=0; j<sz1; j++)
			{
				AttributeValueModel value = values.get(j);
				if (value.getPrefix().equals("+"))
				{
					price = price + value.getPrice();
				}
				else if (value.getPrefix().equals("-"))
				{
					price = price - value.getPrice();
				}
			}

			model.setCartPrice(price);

			totalCartPrice = totalCartPrice + (price * model.getCartQuantity());
		}
		setCartPrice(totalCartPrice);
	}
	
	public void clearProducts() {
		products.clear();
		cartPrice = 0.0;
		uploadCartRequired = true;
	}

	public void setProducts(List<DetailedProductModel> products) {
		this.products = products;
	}

	public int getDiscountCategoryQuantities(int category) {
		int quantity = 0;
		if (category > 0)
		{
			List<DetailedProductModel> productModels = getProducts();
			int sz = productModels.size();
			for (int i= 0; i < sz; i++)
			{
				DetailedProductModel productModel = productModels.get(i);
				if (category == productModel.getDiscountCategory())
				{
					quantity = quantity + productModel.getCartQuantity();
				}
			}
		}
		return quantity;
	}

	public double getCartPrice() {
		return cartPrice;
	}

	public void setCartPrice(double cartPrice) {
		this.cartPrice = cartPrice;
	}

	public String getCartContents()
	{
		String str = "";

		List<DetailedProductModel> productModels = getProducts();
		int sz = productModels.size();

		str += "{\"cart\":[";
		if (sz == 0)
		{
			str += "{\"productId\":0,\"quantity\":0}";
		}
		else
		{
			for (int i= 0; i < sz; i++)
			{
				DetailedProductModel productModel = productModels.get(i);
				int id = productModel.getId();
				int quantity = productModel.getCartQuantity();
				if (i > 0) str +=",";
				str += "{\"productId\":" + id + ",\"quantity\":" + quantity;
				List<AttributeValueModel> values = productModel.getCartOptions();
				int osz = values.size();

				if (osz > 0)
				{
					str += ",\"options\":[";
					for (int j= 0; j < osz; j++)
					{
						AttributeValueModel valueModel = values.get(j);
						int aid = valueModel.getAttributeId();
						int vid = valueModel.getId();
						if (j > 0) str = str + ",";
						str += "{\"optionsId\":" + aid + ",\"optionsValuesId\":" + vid + "}";
					}
					str += "]";
				}
				str += "}";
			}
		}
		str += "]}";

		return str;
	}

	public boolean isUploadCartRequired() {
		return uploadCartRequired;
	}

	public void setUploadCartRequired(boolean cartUpdated) {
		this.uploadCartRequired = cartUpdated;
	}

}
